package com.tssup.fesco.service.impl;


import com.google.common.collect.Lists;
import com.tssup.fesco.sales.goods.persistent.pojo.ISearchHotKey;
import com.tssup.fesco.sales.goods.persistent.pojo.RGoods;
import com.tssup.fesco.search.dao.B2CRGoodsDao;
import com.tssup.fesco.search.dao.ESClient;
import com.tssup.fesco.search.dao.ISearchHotKeyDao;
import com.tssup.fesco.service.UpdateIndexService;
import com.tssup.fesco.util.TaskLogger;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;


/**
 * 更新索引服务
 * @author jiashen
 */
@Service
public class UpdateIndexServiceImpl implements UpdateIndexService {

    private final String indexName;
    private final String typeName;
    private final String hotKeyTypeName;
    private final String historyTypeName;
    private final Client client;

    @Autowired
    private TaskLogger taskLogger;

    @Autowired
    private B2CRGoodsDao b2CRGoodsDao;

    @Autowired
    private ISearchHotKeyDao iSearchHotKeyDao;

    @Autowired
    private GoodsInfoService goodsInfoService;

    public UpdateIndexServiceImpl(Environment env, ESClient esClient) {
        super();
        indexName = env.getProperty("elasticsearch.searchArgs.indexName");
        typeName = env.getProperty("elasticsearch.searchArgs.typeName");
        hotKeyTypeName = env.getProperty("elasticsearch.searchArgs.hotKeyTypeName");
        historyTypeName = env.getProperty("elasticsearch.searchArgs.historyTypeName");
        client = esClient.getESClient();
    }

    //public boolean updateLatelyIndex() {
    //    logger.info("Updating lately index...");
    //
    //    List<B2CRGoods> latelyB2CRGoodes = b2CRGoodsDao.getLatelyGoods();
    //
    //    boolean updateStatus = bulkUpdate(latelyB2CRGoodes);
    //    if (updateStatus) {
    //        logger.info("Update lately index complete.");
    //    }
    //    return updateStatus;
    //}

    @Override
    public void updateAllIndex() throws Exception {
        taskLogger.info("Updating all index...");
        List<RGoods> allB2CRGoodses = b2CRGoodsDao.getAllGoods();
        bulkUpdate(allB2CRGoodses);
        taskLogger.info("Update all index complete.");
    }

    private void bulkUpdate (List<RGoods> b2CRGoodses) throws Exception {

        if (b2CRGoodses.size() == 0) {
            return;
        }

        BulkRequestBuilder bulkRequest = client.prepareBulk();
        for (RGoods b2CRGoods : b2CRGoodses) {
            Integer skuId = b2CRGoods.getSkuId();
            HashMap<String, Object> salesStatus = goodsInfoService.getSalesStatus(skuId);
            HashMap<String, Object> goodsInfo = goodsInfoService.getGoodsInfo(skuId);

            bulkRequest.add(
                client.prepareIndex(indexName, typeName, Integer.toString(skuId))
                    .setSource(jsonBuilder()
                        .startObject()
                        .field("sku_id", skuId)
                        .field("sku_code", b2CRGoods.getSkuCode())
                        .field("name", b2CRGoods.getName())
                        .field("sku_title", b2CRGoods.getSkuTitle())
                        .field("sub_title", b2CRGoods.getSubTitle())
                        .field("spu", b2CRGoods.getSpu())
                        .field("classify", b2CRGoods.getClassify())
                        .field("del_status", b2CRGoods.getDelStatus())
                        .field("del_date", b2CRGoods.getDelDate())
                        .field("create_date", b2CRGoods.getCreateDate())
                        .field("show_home_page", b2CRGoods.getShowHomePage())
                        .field("sales_price", goodsInfo.get("sales_price"))
                        .field("pic_path", goodsInfo.get("pic_path"))

                        // 分类信息
                        .field("second_catalog_id", goodsInfo.get("second_catalog_id"))
                        .field("second_catalog_name", goodsInfo.get("second_catalog_name"))
                        .field("second_catalog_is_show", goodsInfo.get("second_catalog_is_show"))
                        .field("third_catalog_id", goodsInfo.get("third_catalog_id"))
                        .field("third_catalog_name", goodsInfo.get("third_catalog_name"))
                        .field("third_catalog_parent_id", goodsInfo.get("third_catalog_parent_id"))
                        .field("third_catalog_is_show", goodsInfo.get("third_catalog_is_show"))

                        // 品牌信息
                        .field("brand_name", goodsInfo.get("brand_name"))
                        .field("brand_id", goodsInfo.get("brand_id"))
                        .field("brand_name_chn_first_char", goodsInfo.get("brand_name_chn_first_char"))
                        .field("brand_status", goodsInfo.get("brand_status"))

                        // 规格信息
                        .field("specification_id_list", goodsInfo.get("specification_id_list"))
                        .field("specification_param_id_list", goodsInfo.get("specification_param_id_list"))
                        .field("specification_list_str", goodsInfo.get("specification_list_str"))

                        .field("sales_volume", goodsInfo.get("sales_volume"))

                        .field("sales_status", salesStatus.get("saleStatus"))
                        .field("show_status", salesStatus.get("showStatus"))

                        .field("na_name", b2CRGoods.getName())
                        .field("na_sku_title", b2CRGoods.getSkuTitle())
                        .field("na_sub_title", b2CRGoods.getSubTitle())
                        .endObject())
            );
        }

        BulkResponse bulkResponse = bulkRequest.execute().actionGet();

        if (bulkResponse.hasFailures()) {
            taskLogger.error("ES bulk update get error: " + bulkResponse.buildFailureMessage());
            throw new Exception("ES bulk update get error: " + bulkResponse.buildFailureMessage());
        }
    }

    /**
     * 更新热词数据方法。需要清空数据，然后再更新
     * @return
     */
    @Override
    public boolean updateHotKeyIndex() {
        try {
            //            清空旧数据
            SearchResponse response = client.prepareSearch(indexName)
                .setTypes(hotKeyTypeName)
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setQuery(QueryBuilders.matchAllQuery())
                .execute()
                .actionGet();

            SearchHits hits = response.getHits();
            if (hits.totalHits() > 0) {
                for (SearchHit hit : hits) {
                    client.prepareDelete(indexName, hotKeyTypeName, hit.getId()).execute().actionGet();
                }
            }

            //            更新数据
            List<ISearchHotKey> searchHotKeys = iSearchHotKeyDao.getAllSearchHotKeys();
            BulkRequestBuilder bulkRequest = client.prepareBulk();
            for (ISearchHotKey searchHotKey : searchHotKeys) {

                bulkRequest.add(
                    client.prepareIndex(indexName, hotKeyTypeName, Integer.toString(searchHotKey.getkId()))
                        .setSource(jsonBuilder()
                            .startObject()
                            .field("k_id", searchHotKey.getkId())
                            .field("hot_key", searchHotKey.getHotKey())
                            .endObject())
                );
            }

            BulkResponse bulkResponse = bulkRequest.execute().actionGet();

            if (bulkResponse.hasFailures()) {
                taskLogger.error("UpdateHotKeyIndex get error: " + bulkResponse.buildFailureMessage());
                return false;
            }

            taskLogger.info("Update hot key index complete.");
            return true;

        } catch (Exception e) {
            taskLogger.error("updateHotKeyIndex get error: ", e);
            return false;
        }
    }

    public void updateHistoryData(String token, String queryStr) throws Exception {
        if (StringUtils.isBlank(token) || StringUtils.isBlank(queryStr)) {
            return;
        }
        //        1、获取旧数据
        SearchResponse response = getHistoryData(token);
        SearchHits hits = response.getHits();
        List<String> newHistoryList = Lists.newArrayList(queryStr);
        if (hits.totalHits() > 0) {
            for (SearchHit hit : hits) {
                Map<String, Object> hitData = hit.getSource();
                List<String> oldHistory = (List<String>) hitData.get("history_list");
                newHistoryList.addAll(
                    oldHistory.stream().filter(keyWord -> ! keyWord.equals(queryStr))
                        .collect(Collectors.toList()));
            }
        }

        List<String> splitNewHistoryList = Lists.partition(newHistoryList, 10).get(0);

        //        2、upsert到索引
        IndexRequest indexRequest = new IndexRequest(indexName, historyTypeName, token)
            .source(jsonBuilder()
                .startObject()
                .field("token", token)
                .field("history_list", splitNewHistoryList)
                .endObject());
        UpdateRequest updateRequest = new UpdateRequest(indexName, historyTypeName, token)
            .doc(jsonBuilder()
                .startObject()
                .field("token", token)
                .field("history_list", splitNewHistoryList)
                .endObject())
            .upsert(indexRequest);
        client.update(updateRequest).get();
    }

    public SearchResponse getHistoryData(String token) {
        return client.prepareSearch(indexName)
            .setTypes(historyTypeName)
            .setQuery(QueryBuilders.termQuery("token", token))
            .execute()
            .actionGet();
    }
}
